import time
from warnings import simplefilter

import redis
import talib as ta

from . import BinanceKlineFactroy
from . import BinanceKlinesTool
from .BinanceKlinesInit import BinanceKlinesInit

simplefilter(action='ignore')
pool = redis.ConnectionPool(host='185.227.152.91', password='hfhdtrDGKGIG', port=6377, db=1, decode_responses=True)
redis = redis.Redis(connection_pool=pool)


class BinanceSignalInit(BinanceKlinesInit):

    def __init__(self, symbol):
        super().__init__(symbol)
        self.score = 0
        self.long_stop_loss = 0
        self.short_stop_loss = 99999

    def set_stop_loss(self):
        self.short_stop_loss = max([
            BinanceKlineFactroy.DIF_top_range(self.klines_1m, -1)['high'].max(),
            BinanceKlineFactroy.DIF_top_range(self.klines_3m, -1)['high'].max(),
            BinanceKlineFactroy.DIF_top_range(self.klines_5m, -1)['high'].max(),
            BinanceKlineFactroy.DIF_top_range(self.klines_15m, -1)['high'].max(),
            BinanceKlineFactroy.DIF_top_range(self.klines_30m, -1)['high'].max(),
            BinanceKlineFactroy.DIF_top_range(self.klines_1h, -1)['high'].max(),
        ])
        self.long_stop_loss = min([
            BinanceKlineFactroy.DIF_bottom_range(self.klines_1m, -1)['low'].min(),
            BinanceKlineFactroy.DIF_bottom_range(self.klines_3m, -1)['low'].min(),
            BinanceKlineFactroy.DIF_bottom_range(self.klines_5m, -1)['low'].min(),
            BinanceKlineFactroy.DIF_bottom_range(self.klines_15m, -1)['low'].min(),
            BinanceKlineFactroy.DIF_bottom_range(self.klines_30m, -1)['low'].min(),
            BinanceKlineFactroy.DIF_bottom_range(self.klines_1h, -1)['low'].min(),
        ])
        redis.set(self.symbol + '_short_stop_loss', self.short_stop_loss)
        redis.set(self.symbol + '_long_stop_loss', self.long_stop_loss)

    def get_score(self, update=False):
        if not update:
            return self.score

        if len(self.klines_1m) < 300 or len(self.klines_15m) < 300:
            return 0
        score = 0
        now_macd_1m = self.now_macd_1m()
        divergence_1m = self.get_divergence_1m()

        last_last_klines_group_1m = BinanceKlineFactroy.klines_group(self.klines_1m, 2)
        last_last_klines_group_1m_state = last_last_klines_group_1m['state'].values[0]

        last_last_klines_group_15m = BinanceKlineFactroy.klines_group(self.klines_15m, 2)
        last_last_klines_group_15m_state = last_last_klines_group_15m['state'].values[0]

        close_max_15m = last_last_klines_group_15m['close'].max()
        last_last_max_price_15m = last_last_klines_group_15m['open'].max()

        if close_max_15m > last_last_max_price_15m:
            last_last_max_price_15m = close_max_15m

        close_min_15m = last_last_klines_group_15m['close'].min()
        last_last_min_price_15m = last_last_klines_group_15m['open'].min()
        if close_min_15m > last_last_min_price_15m:
            last_last_min_price_15m = close_min_15m

        last_last_max_price_1m = last_last_klines_group_1m['high'].max()
        last_last_min_price_1m = last_last_klines_group_1m['low'].min()

        macd_15m = self.klines_15m['MACD'].values[-1]

        score_details = ''

        # 计算分数
        if last_last_klines_group_1m_state == 1:
            if self.now_price >= self.MA_210_1m() * 1.005 and self.now_price >= last_last_max_price_1m and now_macd_1m > 0:
                score_details += '①'
                score += 1
            if divergence_1m == 1 and now_macd_1m > 0:
                score_details += '②'
                score += 1

        if last_last_klines_group_15m_state == 1:
            if self.now_price >= last_last_max_price_15m * 0.999 and macd_15m > 0:
                score_details += '③'
                score += 2

        if last_last_klines_group_1m_state == -1:

            if self.now_price <= self.MA_210_1m() * 0.995 and self.now_price <= last_last_min_price_1m and now_macd_1m < 0:
                score_details += '④'
                score -= 1
            if divergence_1m == -1 and now_macd_1m < 0:
                score_details += '⑤'
                score -= 1

        if last_last_klines_group_15m_state == -1:
            if self.now_price <= last_last_min_price_15m * 1.001 and macd_15m < 0:
                score_details += '⑥'
                score -= 2
        redis.set(self.symbol + '_score_details', score_details)
        self.score = score
        return score

    def MA_210_1m(self):
        return float(ta.MA(self.klines_1m['close'][-210:].values, 210)[-1:])

    def now_macd_1m(self):
        return self.klines_1m['MACD'].values[-1]

    def get_divergence_1m(self):
        divergence_1m = self.divergence_1m
        if divergence_1m == -1:
            if redis.ttl('ETCUSDT_divergence_1m') < 59:
                redis.set(self.symbol + '_divergence_1m', -1, ex=60)
                redis.set(self.symbol + '_last_time_bottom_divergence_1m', self.klines_1m['date'].values[-1])
            return -1
        elif divergence_1m == 1:
            if redis.ttl('ETCUSDT_divergence_1m') < 59:
                redis.set(self.symbol + '_divergence_1m', 1, ex=60)
                redis.set(self.symbol + '_last_time_top_divergence_1m', self.klines_1m['date'].values[-1])
            return 1
        else:
            return redis.get(self.symbol + '_divergence_1m')  # 返回一分钟内背离

    def MA_210_15m(self):
        return float(ta.MA(self.klines_15m['close'][-210:].values, 210)[-1:])

    def now_macd_15m(self):
        return self.klines_15m['MACD'].values[-1]

    def _kline_update(self):
        self.score = self.get_score(update=True)
        redis.set(self.symbol + '_now_date', self.now_date)
        redis.set(self.symbol + '_score', self.score)
        redis.set(self.symbol + '_now_price', self.now_price)
        redis.set(self.symbol + '_MA210_1m', self.MA_210_1m())
        redis.set(self.symbol + '_MA210_15m', self.MA_210_15m())
        redis.set(self.symbol + '_now_macd_1m', self.now_macd_1m())
        redis.set(self.symbol + '_now_macd_15m', self.now_macd_15m())

        klines_change_date_1m = self.klines_1m.loc[self.klines_1m['state'] != 0]['date'].values
        klines_change_date_15m = self.klines_15m.loc[self.klines_15m['state'] != 0]['date'].values

        klines_change_1m = "[" + str(klines_change_date_1m[-3]) + "] => [" + \
                           str(klines_change_date_1m[-2]) + "] => [" + \
                           str(klines_change_date_1m[-1]) + "]"
        klines_change_15m = "[" + str(klines_change_date_15m[-3]) + "] => [" + \
                            str(klines_change_date_15m[-2]) + "] => [" + \
                            str(klines_change_date_15m[-1]) + "]"

        redis.set(self.symbol + '_klines_change_1m', klines_change_1m)
        redis.set(self.symbol + '_klines_change_15m', klines_change_15m)

        self.set_stop_loss()
        self._score_update(self.score, self.now_price)

    def _score_update(self, score, now_price):
        pass

    def ws_date_interval(self):
        last_date = str(self.now_date)
        last_date = time.strptime(last_date, "%Y-%m-%d %H:%M:%S")
        last_date = time.mktime(last_date)
        return time.time() - last_date
